/**********************************************************************************
 * 文件名称：bsp.c
 * 功能说明：Board Support Package板级支持包函数
 * 作者：laud（qq：554163925）
 * 修改记录：
 **********************************************************************************/
#include "bsp.h"



/*
 **********************************************************************************
 *	函 数 名: bsp_Init
 *	功能说明: 板载各功能模块初始化
 *	形 	  参: 无 
 *	返 回 值: 无
 **********************************************************************************
 */ 
void bsp_Init(void)
{	
	SystemCoreClockUpdate();
	
	bsp_InitUart();
	bsp_InitLed();

	bsp_InitTimer();
}	




/*
 **********************************************************************************
 *	函 数 名: bsp_SystemInit
 *	功能说明: 系统时钟初始化函数
 *	形     参:  无
 *	返 回 值: 无
 **********************************************************************************
*/
void bsp_SystemInit(void)
{   
	ErrorStatus HSEStartUpStatus;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 
		
	RCC_DeInit();     					//RCC system reset(for debug purpose),RCC寄存器初始化
	RCC_HSEConfig(RCC_HSE_ON); 			//Enable HSE   
	HSEStartUpStatus = RCC_WaitForHSEStartUp();	// Wait till HSE is ready 

	if(HSEStartUpStatus == SUCCESS)     //等待外部时钟启动
	{
    	RCC_PLLCmd(DISABLE);    		//配置前先关闭主PLL
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);		//选择PLL为系统时钟
//		FLASH_PrefetchBufferCmd(ENABLE);				//开启Flash预取功能
//		FLASH_SetLatency(FLASH_Latency_1);				//FLASH延迟2个周期，和STM32超频比较相关
																							
		RCC_HCLKConfig(RCC_SYSCLK_Div1);  	//HCLK,AHB设置1分频
		RCC_PCLK1Config(RCC_HCLK_Div4); 	//PCLK1，APB1时钟，为HCLK的4分频
		RCC_PCLK2Config(RCC_HCLK_Div2);   	//PCLK2，APB2时钟，为HCLK的2分频

		//PLLCLK = HSE时钟 25MHz / 25 * 336 / 2   = 168 mhz
		//使用USB_OTG分频 25MHZ / 25 *336 / 7 = 48 mhz
		RCC_PLLConfig(RCC_PLLSource_HSE,8,336,2,4);	//PLL时钟配置，外部晶振25mhz
		
		RCC_PLLCmd(ENABLE);					//PLL时钟开启 				
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)	//等待PLL启动完成
		{}

		// Wait till PLL is used as system clock source 
		while(RCC_GetSYSCLKSource() != 0x08)	//检查是否将HSE 9倍频后作为系统时钟????????????
		{}
	}
	
}

void bsp_Idle(void)
{
		
}

void bsp_RunPer1ms(void)
{


}

void bsp_RunPer10ms(void)
{
//	LED1=~LED1;
//	TMR_100msUpdateRequest();
}


/*
*********************************************************************************************************
*	函 数 名: bsp_DelayMS
*	功能说明: 为了让底层驱动在带RTOS和裸机情况下有更好的兼容性
*             专门制作一个阻塞式的延迟函数，在底层驱动中ms毫秒延迟主要用于初始化，并不会影响实时性。
*	形    参: n 延迟长度，单位1 ms
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_DelayMS(uint32_t _ulDelayTime)
{
	bsp_DelayUS(1000*_ulDelayTime);
}


/*
*********************************************************************************************************
*	函 数 名: bsp_DelayUS
*	功能说明: 这里的延时采用CPU的内部计数实现，32位计数器
*             	OSSchedLock(&err);
*				bsp_DelayUS(5);
*				OSSchedUnlock(&err); 根据实际情况看看是否需要加调度锁或选择关中断
*	形    参: _ulDelayTime  延迟长度，单位1 us
*	返 回 值: 无
*   说    明: 1. 主频168MHz的情况下，32位计数器计满是2^32/168000000 = 25.565秒
*                建议使用本函数做延迟的话，延迟在1秒以下。  
*             2. 实际通过示波器测试，微妙延迟函数比实际设置实际多运行0.25us左右的时间。
*             下面数据测试条件：
*             （1）. MDK5.15，优化等级0, 不同的MDK优化等级对其没有影响。
*             （2）. STM32F407IGT6
*             （3）. 测试方法：
*				 GPIOI->BSRRL = GPIO_Pin_8;
*				 bsp_DelayUS(10);
*				 GPIOI->BSRRH = GPIO_Pin_8;
*             -------------------------------------------
*                测试                 实际执行
*             bsp_DelayUS(1)          1.2360us
*             bsp_DelayUS(2)          2.256us
*             bsp_DelayUS(3)          3.256us
*             bsp_DelayUS(4)          4.256us
*             bsp_DelayUS(5)          5.276us
*             bsp_DelayUS(6)          6.276us
*             bsp_DelayUS(7)          7.276us
*             bsp_DelayUS(8)          8.276us
*             bsp_DelayUS(9)          9.276us
*             bsp_DelayUS(10)         10.28us
*            3. 两个32位无符号数相减，获取的结果再赋值给32位无符号数依然可以正确的获取差值。
*              假如A,B,C都是32位无符号数。
*              如果A > B  那么A - B = C，这个很好理解，完全没有问题
*              如果A < B  那么A - B = C， C的数值就是0xFFFFFFFF - B + A + 1。这一点要特别注意，正好用于本函数。
*********************************************************************************************************
*/
void bsp_DelayUS(uint32_t _ulDelayTime)
{
    uint32_t tCnt, tDelayCnt;
	uint32_t tStart;
		
	tStart = (uint32_t)CPU_TS_TmrRd();                       /* 刚进入时的计数器值 */
	tCnt = 0;
	tDelayCnt = _ulDelayTime * (SystemCoreClock / 1000000);	 /* 需要的节拍数 */ 		      

	while(tCnt < tDelayCnt)
	{
		tCnt = (uint32_t)CPU_TS_TmrRd() - tStart; /* 求减过程中，如果发生第一次32位计数器重新计数，依然可以正确计算 */	
	}
}

/*
*********************************************************************************************************
*	函 数 名: BSP_CPU_ClkFreq
*	功能说明: 获取系统时钟，uCOS-II需要使用
*	形    参: 无
*	返 回 值: 系统时钟
*********************************************************************************************************
*/
CPU_INT32U  BSP_CPU_ClkFreq (void)
{
    RCC_ClocksTypeDef  rcc_clocks;

    RCC_GetClocksFreq(&rcc_clocks);
    return ((CPU_INT32U)rcc_clocks.HCLK_Frequency);
}

/*
*********************************************************************************************************
*	函 数 名: BSP_Tick_Init
*	功能说明: 初始化系统滴答时钟做为uCOS-II的系统时钟节拍，1ms一次
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void BSP_Tick_Init (void)
{
    CPU_INT32U  cpu_clk_freq;
    CPU_INT32U  cnts;
    
    cpu_clk_freq = BSP_CPU_ClkFreq();                           /* 获取系统时钟  */
    
#if (OS_VERSION >= 30000u)
    cnts  = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;     
#else
    cnts  = cpu_clk_freq / (CPU_INT32U)OS_TICKS_PER_SEC;        /* 获得滴答定时器的参数  */
#endif
    
	OS_CPU_SysTickInit(cnts);                                   /* 这里默认的是最低优先级            */
}



